# encoding=utf-8
"""VascularService.py
    - author: 陆嘉懿
    - note:
        - tacom:
            - 由于并发问题，注释mkdir的部分，到其他框架代码中进行统一创建
            - 重建常量信息，减少代码中出现常量的部分
"""
import json

from .VascularTools import *
from .VascularDirFactory import VascularDirFactory
from seg_system import multibatch
from seg_system import ApplicationConfig
from seg_common import ConsoleService
from multiprocessing.dummy import Pool as ThreadPool
from seg_system import ApplicationConfig
from seg_system.LongTaskStatusUpload import IStatusUpload
from seg_common.annotation import TimeRecorder

from seg_system.vascular.service.VascularToolsForBatch.VascularBatchLoader.VascularBatchLoaderImpl import *
from seg_system.vascular.service.VascularToolsForBatch.VascularEachProcessor.CNFDForBatch import CNFDForBatch
from seg_system.vascular.service.VascularToolsForBatch.VascularEachProcessor.CNBDForBatch import CNBDForBatch, CNBDNoneBorderForBatch
from seg_system.vascular.service.VascularToolsForBatch.VascularEachProcessor.CTBDForBatch import CTBDForBatch
from seg_system.vascular.service.VascularToolsForBatch.VascularEachProcessor.CNFLForBatch import CNFLForBatch
from seg_system.vascular.service.VascularToolsForBatch.VascularEachProcessor.VascularForBatchBase import \
    VascularForBatchBase


class VascularService:
    worker = ThreadPool(ApplicationConfig.SystemConfig.VASCULAR_NUM_WORKER)
    vascular_data = VascularBatchLoaderFactory()
    vascular_cnfd = CNFDForBatch()
    # vascular_cnbd = CNBDForBatch()
    vascular_cnbd = CNBDNoneBorderForBatch()
    vascular_ctbd = CTBDForBatch()
    vascular_cnfl = CNFLForBatch()

    def predict_start(self, batch_saver: multibatch.SaveService,
                      vascular_saver: VascularDirFactory,
                      segmentation_choice: list, pre_message: str, **kwargs):
        enhance_choice = kwargs.get("enhance_choice")

        if segmentation_choice[0] == -1:
            ConsoleService.console_log(pre_message + 'have not pre task segmentation, vascular dont start')
            return

        self.vascular_for_batch(batch_saver.NORMAL_1, vascular_saver, pre_message, False, **kwargs)
        if enhance_choice[0] != -1:
            self.vascular_for_batch(batch_saver.ENHANCE_1, vascular_saver, pre_message, True, **kwargs)

        # 旧代码写着备份、回退用
        # if segmentation_choice[0] != -1:  ### 逻辑错误，应该在增强的基础下执行  ###
        #     self.read_path(batch_saver.ENHANCE_1, vascular_saver, pre_message, True, **kwargs)
        # self.read_path(batch_saver.NORMAL_1, vascular_saver, pre_message, False, **kwargs)

    def vascular_for_batch(self, file_pathname: str, vascular_saver: VascularDirFactory,
                           pre_message: str, is_enhance: bool = False, **kwargs):
        # 注意这里的path不应该用明文，这些目录时常根据需求变幻，单纯没时间写了
        cnfd_save_path = vascular_saver.ENHANCE_0 if is_enhance else vascular_saver.NORMAL_0
        refine_save_path = vascular_saver.ENHANCE_1 if is_enhance else vascular_saver.NORMAL_1
        branch_save_path = vascular_saver.ENHANCE_1_0 if is_enhance else vascular_saver.NORMAL_1_0
        seg_save_path = vascular_saver.ENHANCE_1_1 if is_enhance else vascular_saver.NORMAL_1_1
        degree_save_path = vascular_saver.ENHANCE_2 if is_enhance else vascular_saver.NORMAL_2
        all_save_path = vascular_saver.ENHANCE_3 if is_enhance else vascular_saver.NORMAL_3

        VascularService.vascular_data.load_data(file_pathname)
        batch = ApplicationConfig.SystemConfig.VASCULAR_BATCH
        stride = ApplicationConfig.SystemConfig.VASCULAR_STRIDE
        thread = ApplicationConfig.SystemConfig.VASCULAR_THREAD
        vascular_dataloader = VascularDataLoader(VascularService.vascular_data, batch, stride, thread)

        vascular_action = ApplicationConfig.SystemConfig.VASCULAR_ACTION
        vascular_process_config = ApplicationConfig.SystemConfig.VASCULAR_PROCESS_CONFIG
        for index, o in enumerate(vascular_dataloader):
            m, i, f = o

            # cnfd 和 ctbd验证
            cnfd_list = VascularService.vascular_cnfd.process(
                m, i, (384, 384), stride, f, cnfd_save_path,
                **vascular_process_config["CNFD"][vascular_action]
            )
            # 这里的代码还是有点问题，对原图进行了修改，导致后续图像不对
            cnbd_list = VascularService.vascular_cnbd.process(
                m.copy(), i, (384, 384), stride, f, "",
                **vascular_process_config["CNBD"][vascular_action],
                refine_save_path=refine_save_path,
                branch_save_path=branch_save_path,
                seg_save_path=seg_save_path
            )
            ctbd_list = VascularService.vascular_ctbd.process(
                m, i, (384, 384), stride, f, "",
                **vascular_process_config["CTBD"][vascular_action],
                refine_save_path=refine_save_path,
                seg_save_path=seg_save_path,
                file_name_list=f
            )
            cnfl_list = VascularService.vascular_cnfl.process(
                m, i, (384, 384), stride, f, degree_save_path,
                **vascular_process_config["CNFL"][vascular_action],
                seg_save_path=seg_save_path,
                file_name_list=f
            )

            # 这个部分需要加一个异步文件存储
            for cnfd, cnbd, ctbd, cnfl, filename in zip(cnfd_list, cnbd_list, ctbd_list, cnfl_list, f):
                t_d = {
                    'CNFL': cnfl / 0.16,
                    'CNFD': cnfd / 0.16,
                    'CTBD': ctbd / 0.16,
                    'CNBD': cnbd / 0.16
                }
                with open(os.path.join(all_save_path, filename) + ".txt", "w") as each_file:
                    each_file.write(json.dumps(t_d))

                ConsoleService.console_log(
                    "{}, CNFL: {}, CNFD: {}, CTBD: {}, CNBD: {}".format(filename,
                                                                        cnfl / 0.16, cnfd / 0.16,
                                                                        ctbd / 0.16, cnbd / 0.16))
            IStatusUpload.update_state_from_kwargs(**kwargs, token=str(f))

    def read_path(self, file_pathname: str, vascular_saver: VascularDirFactory,
                  pre_message: str, is_enhance: bool = False, **kwargs):
        # @TimeRecorder.time_record()

        def deal(filename: str):
            # 函数调用的顺序不能改变，因为后面函数中有部分数据是前面函数生成的
            """
            CNFD函数接口：.multibatch import SaveService
            调用方式：CNFD(file_pathname,filename)
            输入：参数分别是file_pathname（文件路径名）以及filename（文件名）  eg:CNFD("D:/mywork/Arbitrary/gt","FJ103.png")
            输出：返回结果是连通域的个数，同时会在文件路径名下生成一个Color文件夹，保存不同连通域的分类效果
            """
            F0 = vascular_saver.ENHANCE_0 if is_enhance else vascular_saver.NORMAL_0
            cnfd = CNFD(file_pathname, filename, F0)
            """
            CNBD函数接口：
            调用方式：CNBD(file_pathname,filename)
            输入：参数分别是file_pathname（文件路径名）以及filename（文件名）  eg:CNFD("D:/mywork/Arbitrary/gt","FJ103.png")
            输出：返回分支点的个数，同时会在文件路径名下生成一个Refinement文件夹保存血管细化的结果，一个Branch_point文件夹保存血管分支点标记的结果
            """
            F1 = vascular_saver.ENHANCE_1 if is_enhance else vascular_saver.NORMAL_1
            F1_0 = vascular_saver.ENHANCE_1_0 if is_enhance else vascular_saver.NORMAL_1_0
            F1_1 = vascular_saver.ENHANCE_1_1 if is_enhance else vascular_saver.NORMAL_1_1
            cnbd = CNBD(file_pathname, filename, F1, F1_0, F1_1)
            """
            CTBD函数接口：
            调用方式：CTBD(file_pathname,filename)
            输入：参数分别是file_pathname（文件路径名）以及filename（文件名）  eg:CNFD("D:/mywork/Arbitrary/gt","FJ103.png")
            输出：返回分支数量
            """
            ctbd = CTBD(file_pathname, filename, F1, F1_1)
            """
            CNFL函数接口：
            调用方式：CNFL(file_pathname,filename)
            输入：参数分别是file_pathname（文件路径名）以及filename（文件名）  eg:CNFD("D:/mywork/Arbitrary/gt","FJ103.png")
            输出：返回所有血管的长度，同时会在文件路径名下生成一个Degree文件夹，保存血管角度的直方图统计，直方图以20度为一个间隔
            """
            F2 = vascular_saver.ENHANCE_2 if is_enhance else vascular_saver.NORMAL_2
            cnfl = CNFL(file_pathname, filename, F1_1, F2)

            # 0.16是图片物理大小，换算成每平方毫米上数量
            F3 = vascular_saver.ENHANCE_3 if is_enhance else vascular_saver.NORMAL_3
            t_d = {
                'CNFL': cnfl / 0.16,
                'CNFD': cnfd / 0.16,
                'CTBD': ctbd / 0.16,
                'cnbd': cnbd / 0.16
            }
            with open(os.path.join(F3, filename) + ".txt", 'w') as f:
                f.write(json.dumps(t_d))

            ConsoleService.console_log(
                "{}, CNFL: {}, CNFD: {}, CTBD: {}, CNBD: {}".format(pre_message + filename, cnfl / 0.16, cnfd / 0.16,
                                                                    ctbd / 0.16,
                                                                    cnbd / 0.16))
            IStatusUpload.update_state_from_kwargs(**kwargs, token=filename)

        VascularService.worker.map(deal, os.listdir(file_pathname))
